/**
 * 判断一个对象是否为逻辑上的空
 *
 * @param value
 * @returns {boolean|boolean}
 * @private
 */
export function _isEmpty(value) {
  return (
      value === undefined ||
      value === null ||
      (typeof value === 'string' && value.trim().length === 0) ||
      (typeof value === 'object' && Object.keys(value).length === 0)
  );
}

/**
 * @description 判断一个对象是否逻辑上不为空
 * @param value
 * @returns {boolean}
 */
export function _nonEmpty(value) {
  return !_isEmpty(value)
}

/**
 * 将空格、回车、Tab转译为html
 *
 * @param str
 * @returns {*|string}
 * @private
 */
export function _html(str) {
  return String(str)
      .replace(/&(?!\w+;)/g, '&amp;')
      .replace(/ /g, '&nbsp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#039;')
      .replace(/\n/g, '<br>')
      .replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;');
}

/**
 * @description 默认命令行样式格式化
 * @param {string} cmd 命令行内容
 * @return {string}
 */
export function _defaultCommandFormatter(cmd) {
  // 过滤ASCII 160空白字符串
  const cmdArr = cmd.replace(/\xA0/g, ' ').split(' ') // 拆分命令
  // 格式化后指令
  let formatted = '';
  let isCmdKey = true;
  cmdArr.forEach((item, idx) => {
    const char = _html(item);
    // 命令名称
    if (isCmdKey) {
      formatted += `<span class="t-cmd-key">${char}</span>`;
      isCmdKey = false;
    } else if (char.length > 0) { // 命令后子命令执行
      formatted += `<span>${char}</span>`;
    }
    // 还原命令里的空格
    if (idx < cmdArr.length - 1) {
      formatted += '<span>&nbsp;</span>'
    }
  })
  return formatted;
}

/**
 * @description  事件监听声明
 * @param dom 需要监听的源
 * @param eventName 事件名称
 * @param handler 事件方法体
 */
export function _eventOn(dom, eventName, handler) {
  dom && dom.addEventListener && dom.addEventListener(eventName, handler);
}

/**
 * @description 移除事件监听
 * @param dom 需要监听的源
 * @param eventName 事件名称
 * @param handler 事件方法体
 */
export function _eventOff(dom, eventName, handler) {
  dom && dom.removeEventListener && dom.removeEventListener(eventName, handler);
}

/**
 * @description 获取光标状态对象
 */
export function _getSelection() {
  if (window.getSelection) {
      return window.getSelection()
  } else {
      return document.getSelection()
  }
}

/**
 * @description 复制文本内容至粘贴板中
 * @param text 文本内容
 */
export function _copyTextToClipboard(text: string) {
  if (!text) {
      return
  }
  text = text.replace(/nbsp;/g, ' ')
  // 是否支持浏览器最新复制方法
  if (navigator && navigator.clipboard) {
      navigator.clipboard.writeText(text).then(() => {
      })
  } else {
      const textArea = document.createElement('textarea')
      textArea.value = text
      textArea.style.position = 'absolute'
      textArea.style.opacity = '0'
      textArea.style.left = '-999999px'
      textArea.style.top = '-999999px'
      document.body.appendChild(textArea)
      textArea.focus()
      textArea.select()
      document.execCommand('copy')
      textArea.remove()
  }
}

/**
 * @description 获取粘贴板中的内容
 */
export function _getClipboardText() {
  if (navigator && navigator.clipboard) {
      return navigator.clipboard.readText();
  } else {
      const pasteTarget = document.createElement('div');
      pasteTarget.contentEditable = 'true';
      const actElem = document.activeElement.appendChild(pasteTarget).parentNode;
      pasteTarget.focus();
      //  可能会失败
      document.execCommand('paste')
      const paste = pasteTarget.innerText;
      actElem.removeChild(pasteTarget);
      return new Promise((res: (val: string) => void) => res(paste));
  }
}

/**
 * @description 判断dom是否是另一个dom的子节点
 * @param target 目标DOM
 * @param parent 父级DOM
 * @param clazz 中断类，检查到当前节点有此类时终端搜索
 * @returns {boolean}
 */
export function _isParentDom(target, parent, clazz = null) {
  while (target) {
      if (target === parent) {
          return true;
      }

      if (clazz && target.classList.contains(clazz)) {
          break
      }
      target = target.parentElement
  }
  return false;
}
/**
 * 点击位置是否在rect内
 * @param point 鼠标点击坐标位置
 * @param rect dom rect内容
 * @returns {boolean}
 */
export function _pointInRect(point, rect) {
  const { x, y } = point;
  const dx = rect.x;
  const dy = rect.y;
  const width = rect.width;
  const height = rect.height;
  return x >= dx && x <= dx + width && y >= dy && y <= dy + height;
}

/**
 * @description 获取当前字符所占字节长度，以此判断中文字符还是英文字符
 * @param val 字符
 * @returns {number} 当前字符所占字节长度
 */
export function _getByteLen(val: string) {
  let len = 0;
  for (let i = 0; i < val.length; i++) {
      if (val[i].match(/[^\x00-\xff]/ig) != null) { // 全角
        len += 2; // 如果是全角，占用两个字节
      } else {
        len += 1; // 半角占用一个字节
      }
  }
  return len;
}

/**
 * @description 延时睡眠等待操作
 * @param time 时长 1000: 1秒
 */
export function _sleep(time) {
  return new Promise((resolve) => setTimeout(resolve, time))
}
